/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.ryan.ohos.extension.util;

import java.math.BigDecimal;

/**
 * 颜色估值器
 *
 * @author wangyin
 * @since 2021/07/02
 */
public class ArgbEvaluator {

    private volatile static ArgbEvaluator sInstance = null;

    public static ArgbEvaluator getInstance() {
        if (sInstance == null) {
            synchronized (ArgbEvaluator.class) {
                if (sInstance == null) {
                    sInstance = new ArgbEvaluator();
                }
            }
        }
        return sInstance;
    }

    private ArgbEvaluator() {
    }

    /**
     * 计算之后的结果
     *
     * @param fraction 数值
     * @param startValue 起始值
     * @param endValue 结束值
     * @return 计算之后的结果
     */
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        int startInt = (Integer) startValue;
        float startA = ((startInt >> 24) & 0xFF) / 255.0F;
        float startR = ((startInt >> 16) & 0xFF) / 255.0F;
        float startG = ((startInt >> 8) & 0xFF) / 255.0F;
        float startB = (startInt & 0xFF) / 255.0F;

        int endInt = (Integer) endValue;
        float endA = ((endInt >> 24) & 0xff) / 255.0F;
        float endR = ((endInt >> 16) & 0xff) / 255.0F;
        float endG = ((endInt >> 8) & 0xff) / 255.0F;
        float endB = (endInt & 0xFF) / 255.0F;

        // convert from sRGB to linear
        startR = (float) Math.pow(startR, 2.2);
        startG = (float) Math.pow(startG, 2.2);
        startB = (float) Math.pow(startB, 2.2);

        endR = (float) Math.pow(endR, 2.2);
        endG = (float) Math.pow(endG, 2.2);
        endB = (float) Math.pow(endB, 2.2);

        // compute the interpolated color in linear space
        float a = BigDecimal.valueOf(startA).add(BigDecimal.valueOf(fraction)
                .multiply(BigDecimal.valueOf(endA)
                        .subtract(BigDecimal.valueOf(startA)))).floatValue();
        float r = BigDecimal.valueOf(startR).add(BigDecimal.valueOf(fraction)
                .multiply(BigDecimal.valueOf(endR)
                        .subtract(BigDecimal.valueOf(startR)))).floatValue();
        float g = BigDecimal.valueOf(startG).add(BigDecimal.valueOf(fraction)
                .multiply(BigDecimal.valueOf(endG)
                        .subtract(BigDecimal.valueOf(startG)))).floatValue();
        float b = BigDecimal.valueOf(startB).add(BigDecimal.valueOf(fraction)
                .multiply(BigDecimal.valueOf(endB)
                        .subtract(BigDecimal.valueOf(startB)))).floatValue();

        // convert back to sRGB in the [0..255] range
        a = a * 255.0F;
        r = (float) Math.pow(r, 1.0 / 2.2) * 255.0F;
        g = (float) Math.pow(g, 1.0 / 2.2) * 255.0F;
        b = (float) Math.pow(b, 1.0 / 2.2) * 255.0F;

        return Math.round(a) << 24 | Math.round(r) << 16 | Math.round(g) << 8 | Math.round(b);
    }
}